<?php

namespace app\api\controller;

use app\api\Api;
use app\model\Sms as SmsModel;

class User extends Api
{
    protected $SmsModel;
    public function __construct()
    {
        $this->SmsModel = new SmsModel();

        //以下字段不允许使用POST修改
        $this->postBlackList = ['user_id', "user_status", "user_createtime", "user_updatetime"];
        //以下字段查询时不会被返回
        // $this->selectFieldList = ["user_name", "user_status"];
        //筛选条件
        $this->searchFilter = [
            "user_id" => "=", //相同筛选
            "user_account" => "="
        ];
        $this->per_page = 20;
        parent::__construct();
    }

    /**
     * 用户登录
     *
     * @return void
     */
    public function login()
    {
        if (!input("user_account")) {
            return jerr('请确认帐号是否正确填写');
        }
        if (!input("user_password")) {
            return jerr('请确认密码是否正确填写');
        }
        $plat = input("plat");
        if ($plat == "admin") {
            // TODO 这里只是一个demo 具体的业务逻辑请自行修改！！！
            if (input("token") && input("code")) {
                $result = captcha_check_api(strtoupper(input("code")), input("token"));
                if (!$result) {
                    return jerr('验证码输入错误！');
                }
            } else {
                return jerr('请输入验证码后登录！');
            }
        }

        $user_account = input("user_account");
        $user_password = input("user_password");
        //登录获取用户信息
        $user = $this->UserModel->login($user_account, $user_password);
        if ($user) {
            //创建一个新的授权
            $access = $this->AccessModel->createAccess($user['user_id'], $this->plat);
            if ($access) {
                cookie('access_token', $access['access_token']);
                return jok('登录成功', ['access_token' => $access['access_token']]);
                // return jok('登录成功', ['access_token' => $access['access_token'], "user_info" => $user]);
            } else {
                return jerr('登录系统异常');
            }
        } else {
            return jerr('帐号或密码错误');
        }
    }

    /**
     * 获取我的信息
     *
     * @return void
     */
    public function getMyInfo()
    {
        //走AccessToken验证
        $error = $this->auth();
        if ($error) {
            return $error;
        }
        //走Rbac验证
        $error = $this->rbac();
        if ($error) {
            return $error;
        }
        //业务逻辑开始 TODO
        $myInfo = $this->user;
        foreach (['user_password', 'user_salt', 'user_accesstoken', 'user_tokentime', 'user_status'] as $key) {
            unset($myInfo[$key]);
        }
        return jok(null, $myInfo);
    }
    /**
     * 修改我的信息
     *
     * @return void
     */
    public function updateMyInfo()
    {
        //走AccessToken验证
        $error = $this->auth();
        if ($error) {
            return $error;
        }
        //走Rbac验证
        $error = $this->rbac();
        if ($error) {
            return $error;
        }
        if (!input("user_name")) {
            return jerr("你确定飘到连名字都可以不要了吗？");
        }
        $data = [
            "user_name" => input("user_name"),
            "user_truename" => input("user_truename"),
            "user_email" => input("user_email"),
            "user_idcard" => input("user_idcard"),
        ];
        $this->UserModel->where("user_id", $this->user['user_id'])->update($data);
        return jok("success");
    }
    /**
     * 用户注册
     *
     * @return void
     */
    public function reg()
    {
        if (!input("phone")) {
            return jerr("手机号不能为空！");
        }
        $phone = input("phone");
        if (!input("code")) {
            return jerr("短信验证码不能为空！");
        }
        $code = input("code");
        if (!input("password")) {
            return jerr("密码不能为空！");
        }
        $password = input("password");
        $name = $phone;
        if (input("name")) {
            $name = input("name");
        }
        if ($this->SmsModel->validSmsCode($phone, $code)) {
            $user = $this->UserModel->where([
                "user_account" => $phone
            ])->find();
            if ($user) {
                return jerr("该手机号已经注册！");
            }
            $result = $this->UserModel->reg($phone, $password, $name);
            if ($result) {
                return jok("用户注册成功");
            } else {
                return jerr("注册失败，请重试！");
            }
        } else {
            return jerr("短信验证码已过期，请重新获取");
        }
    }

    /**
     * 修改密码
     *
     * @return void
     */
    public function motifyPassword()
    {
        //走AccessToken验证
        $error = $this->auth();
        if ($error) {
            return $error;
        }
        //走Rbac验证
        $error = $this->rbac();
        if ($error) {
            return $error;
        }
        if (!input("user_password")) {
            return jerr("你必须要输入你的原密码！");
        }
        if (!input("user_newpassword")) {
            return jerr("你必须输入一个新的密码！");
        }
        $old_password = input("user_password");
        $new_password = input("user_newpassword");
        if (strlen($new_password) < 6 || strlen($new_password) > 16) {
            return jerr("新密码因为6-16位！");
        }
        if ($this->user['user_password'] != encodePassword($old_password, $this->user['user_salt'])) {
            return jerr("原密码输入不正确，请重试！");
        }
        $result = $this->UserModel->resetPassword($this->user['user_account'], $new_password);
        // die;
        if ($result) {
            return jok("密码已重置，请使用新密码登录");
        } else {
            return jerr("注册失败，请重试！");
        }
    }

    /**
     * 重置密码
     *
     * @return void
     */
    public function resetPassword()
    {
        if (!input("phone")) {
            return jerr("手机号不能为空！");
        }
        if (!input("code")) {
            return jerr("短信验证码不能为空！");
        }
        if (!input("password")) {
            return jerr("密码不能为空！");
        }
        $phone = input("phone");
        $code = input("code");
        $password = input("password");
        if ($this->SmsModel->validSmsCode($phone, $code)) {
            $user = $this->UserModel->where([
                "user_account" => $phone
            ])->find();
            if (!$user) {
                return jerr("该手机号尚未注册！");
            }
            $result = $this->UserModel->resetPassword($phone, $password);
            if ($result) {
                return jok("密码已重置，请使用新密码登录");
            } else {
                return jerr("注册失败，请重试！");
            }
        } else {
            return jerr("短信验证码已过期，请重新获取");
        }
    }

    /**
     * 微信小程序登录
     *
     * @return void
     */
    public function wxAppLogin()
    {
        $appid = config('wxapp_appid'); //小程序APPID
        $appkey = config("wxapp_appkey"); //小程序的APPKEY
        if (input("?code")) {
            $code = input("code");
            $ret = httpGetFull("https://api.weixin.qq.com/sns/jscode2session?appid=" . $appid . "&secret=" . $appkey . "&js_code=" . $code . "&grant_type=authorization_code");
            try {
                $ret = json_decode($ret);
                if (property_exists($ret, 'session_key')) {
                    $session_key = $ret->session_key;
                    $openid = $ret->openid;
                    return jok(null, [
                        "session_key" => $session_key,
                        "openid" => $openid
                    ]);
                } else {
                    return jerr("获取session_key失败");
                }
            } catch (\Exception $e) {
                return jerr("微信返回数据异常");
            }
        } else {
            return jerr("你应该传code给我");
        }
    }
    /**
     * 微信小程序手机号解密
     *
     * @return void
     */
    public function wxPhoneDecodeLogin()
    {
        $appid = config('wxapp_appid'); //小程序APPID
        // $appkey = config("wxapp_appkey"); //小程序的APPKEY
        //判断POST的数据中是否包含code/iv(向量)/encryptedData(原始加密数据)/session_key(会话key)/openid
        if (input("?code") && input("?iv") && input("?encryptedData") && input("?session_key") && input("?openid")) {
            // $code = input("code");
            $iv = input("iv");
            $encryptedData = input("encryptedData");
            $session_key = input("session_key");
            // $openid = input("openid");
            try {
                $isOk = true;
                $aesKey = base64_decode($session_key);
                if (strlen($iv) != 24) {
                    //非合法解密向量
                    $isOk = false;
                }
                $aesIV = base64_decode($iv);
                $aesCipher = base64_decode($encryptedData);
                $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
                $dataObj = json_decode($result);
                if ($dataObj  == NULL) {
                    //解密数据异常
                    $isOk = false;
                }
                if ($dataObj->watermark->appid != $appid) {
                    //这个就没啥用了 解密成功就行 管他是不是自己的 这是微信demo的 我没改。
                    $isOk = false;
                }
                if ($isOk) {
                    $phone = $dataObj->phoneNumber; //得到手机号
                    $this->user = $this->UserModel->loginByAccount($phone);
                    if (!$this->user) {
                        return jerr("用户未注册，请先注册！");
                    } else {
                        //创建一个新的授权
                        $access = $this->AccessModel->createAccess($this->user['user_id'], 'wxapp');
                        if ($access) {
                            cookie('access_token', $access['access_token']);
                            return jok('登录成功', ['access_token' => $access['access_token']]);
                            // return jok('登录成功', ['access_token' => $access['access_token'], "user_info" => $user]);
                        } else {
                            return jerr('登录系统异常');
                        }
                    }
                } else {
                    return jerr("解密手机号失败，请重新授权登录！");
                }
            } catch (\Exception $e) {
                return jerr("解密出了问题 " . $e->getMessage());
            }
        } else {
            return jerr("是不是所有的参数都POST过来了");
        }
    }
    /**
     * 禁用用户
     *
     * @return void
     */
    public function disable()
    {
        //走AccessToken验证
        $error = $this->auth();
        if ($error) {
            return $error;
        }
        //走Rbac验证
        $error = $this->rbac();
        if ($error) {
            return $error;
        }
        if (!input($this->pk)) {
            return jerr("禁用失败,缺少参数");
            exit;
        }
        $this->pk_value = input($this->pk);
        $map[$this->pk] = $this->pk_value;
        if (isInteger($this->pk_value)) {
            $item = db($this->table)->where($map)->find();
            if (empty($item)) {
                return jerr("没有这条记录，禁用失败");
                exit;
            }
            if ($item[$this->pk] == 1) {
                return jerr("超级管理员不允许操作！");
                exit;
            }
        } else {
            $list = explode(',', $this->pk_value);
            $map[$this->pk] = ['in', $list];
        }
        db($this->table)->where($map)->where($this->pk . " > 1")->update([
            $this->table . "_status" => 1,
            $this->table . "_updatetime" => time(),
        ]);
        return jok();
    }

    /**
     * 启用用户
     *
     * @return void
     */
    public function enable()
    {
        //走AccessToken验证
        $error = $this->auth();
        if ($error) {
            return $error;
        }
        //走Rbac验证
        $error = $this->rbac();
        if ($error) {
            return $error;
        }
        if (!input($this->pk)) {
            return jerr("启用失败,缺少参数");
            exit;
        }
        $this->pk_value = input($this->pk);
        $map[$this->pk] = $this->pk_value;
        if (isInteger($this->pk_value)) {
            $item = db($this->table)->where($map)->find();
            if (empty($item)) {
                return jerr("没有这条记录，启用失败");
                exit;
            }
            if ($item[$this->pk] == 1) {
                return jerr("超级管理员不允许操作！");
                exit;
            }
        } else {
            $list = explode(',', $this->pk_value);
            $map[$this->pk] = ['in', $list];
        }
        db($this->table)->where($map)->where($this->pk . " > 1")->update([
            $this->table . "_status" => 0,
            $this->table . "_updatetime" => time(),
        ]);
        return jok();
    }

    /**
     * 删除用户
     *
     * @return void
     */
    public function delete()
    {
        //走AccessToken验证
        $error = $this->auth();
        if ($error) {
            return $error;
        }
        //走Rbac验证
        $error = $this->rbac();
        if ($error) {
            return $error;
        }
        if (!input($this->pk)) {
            return jerr("删除失败,缺少参数");
            exit;
        }
        $this->pk_value = input($this->pk);
        $map[$this->pk] = $this->pk_value;
        if (isInteger($this->pk_value)) {
            $item = db($this->table)->where($map)->find();
            if (empty($item)) {
                return jerr("没有这条记录，删除失败");
                exit;
            }
            if ($item[$this->pk] == 1) {
                return jerr("超级管理员不允许操作！");
                exit;
            }
        } else {
            $list = explode(',', $this->pk_value);
            $map[$this->pk] = ['in', $list];
        }
        db($this->table)->where($map)->where($this->pk . " > 1")->delete();
        return jok();
    }
    /**
     * 修改用户
     *
     * @return void
     */
    public function update()
    {
        //走AccessToken验证
        $error = $this->auth();
        if ($error) {
            return $error;
        }
        //走Rbac验证
        $error = $this->rbac();
        if ($error) {
            return $error;
        }
        if (!input($this->pk)) {
            return jerr("修改失败,缺少参数");
            exit;
        }
        $this->pk_value = input($this->pk);
        if (!isInteger($this->pk_value)) {
            return jerr("修改失败,参数错误");
            exit;
        }
        $map[$this->pk] = $this->pk_value;
        $item = db($this->table)->where($map)->find();
        if (empty($item)) {
            return jerr("没有这条记录，修改失败");
            exit;
        }
        if (intval($this->pk_value) == 1) {
            return jerr("无法修改超管用户信息");
            exit;
        }
        $data = [];
        foreach (input("post.") as $k => $v) {
            if (in_array($k, $this->postBlackList)) {
                continue;
            } else {
                $data[$k] = $v;
            }
        }
        if (!input($this->table . "_account")) {
            return jerr("帐号必须填写");
        }
        $user = $this->UserModel->getUserByAccount($data[$this->table . "_account"]);
        if ($user && $user[$this->pk] != $item[$this->pk]) {
            return jerr("帐号已存在，请重新输入");
        }
        if (empty($data[$this->table . "_password"])) {
            unset($data[$this->table . "_password"]);
        } else {
            //设置密码
            $salt = getRandString(4);
            $password = $data[$this->table . "_password"];
            $password = encodePassword($password, $salt);
            $data[$this->table . "_salt"] = $salt;
            $data[$this->table . "_password"] = $password;
        }
        $data[$this->table . "_updatetime"] = time();
        db($this->table)->where($this->pk, $this->pk_value)->update($data);
        return jok();
    }

    /**
     * 添加用户
     *
     * @return void
     */
    public function add()
    {
        //走AccessToken验证
        $error = $this->auth();
        if ($error) {
            return $error;
        }
        //走Rbac验证
        $error = $this->rbac();
        if ($error) {
            return $error;
        }
        if (!input($this->table . "_account")) {
            return jerr("帐号必须填写");
        }
        if (!input($this->table . "_password")) {
            return jerr("密码必须填写");
        }
        $data = [];
        foreach (input("post.") as $k => $v) {
            if (in_array($k, $this->postBlackList)) {
                continue;
            } else {
                $data[$k] = $v;
            }
        }
        $user = $this->UserModel->getUserByAccount($data[$this->table . "_account"]);
        if ($user) {
            return jerr("帐号已存在，请重新输入");
        }
        $salt = getRandString(4);
        $password = $data[$this->table . "_password"];
        $password = encodePassword($password, $salt);
        $data[$this->table . "_salt"] = $salt;
        $data[$this->table . "_password"] = $password;
        $data[$this->table . "_updatetime"] = time();
        $data[$this->table . "_createtime"] = time();
        db($this->table)->insert($data);
        return jok();
    }
    /**
     * 获取所有列表方法 支持查询 排序 分页 需要请覆写之类中的方法即可
     *
     * @return void
     */
    public function lists()
    {
        //走AccessToken验证
        $error = $this->auth();
        if ($error) {
            return $error;
        }
        // //走Rbac验证
        $error = $this->rbac();
        if ($error) {
            return $error;
        }
        $map = [];
        $filter = input();
        if (input("per_page")) {
            $this->per_page = intval(input("per_page"));
        }
        if (input("keyword") && input("search")) {
            //存在查询条件
            if (array_key_exists(input("search"), $this->searchFilter)) {
                switch ($this->searchFilter[input("search")]) {
                    case "like":
                        $map[input("search")] = ["like", "%" . urldecode(input("keyword")) . "%"];
                        break;
                    case "=":
                        $map[input("search")] = urldecode(input("keyword"));
                        break;
                    default:
                }
            }
        } else {
            foreach ($filter as $k => $v) {
                if (array_key_exists($k, $this->searchFilter)) {
                    switch ($this->searchFilter[$k]) {
                        case "like":
                            $map[$k] = ["like", "%" . urldecode($v) . "%"];
                            break;
                        case "=":
                            $map[$k] = urldecode($v);
                            break;
                        default:
                    }
                }
            }
        }
        $order = $this->pk . " desc";
        if (input('order')) {
            $order = urldecode(input('order'));
        }
        $field = "*";
        if (count($this->selectFieldList) > 0) {
            $field = $this->pk;
            foreach ($this->selectFieldList as $selectField) {
                $field .= "," . $selectField;
            }
        }
        $join = [
            ['group group', 'group.group_id = user.user_group', 'left']
        ];
        $field .= ",group.group_name";
        $datalist = db($this->table)->alias($this->table)->join($join)->field($field)->where($map)->order($order)->paginate($this->per_page, false);
        return jok('success', $datalist);
    }
}
